package mc.support.web.action;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.*;

import java.util.Date;

import static mc.support.web.WebConstants.GLOBAL_DATE_FORMAT;

/**
 * Created with IntelliJ IDEA. <br/>
 * Author: francis Yun    <br/>
 * Date: 2013-11-23  <br/>
 */
public class DefaultResultDecoratorImpl implements ResultDecorator {

    private static SerializeConfig defaultSerializeConfig = new SerializeConfig();

    static {
        defaultSerializeConfig.put(Date.class, new SimpleDateFormatSerializer(GLOBAL_DATE_FORMAT));
    }

    private PropertyPreFilter propertyPreFilter;
    private SerializeConfig serializeConfig;

    public static SerializeConfig getDefaultSerializeConfig() {
        return defaultSerializeConfig;
    }

    public static void setDefaultSerializeConfig(SerializeConfig defaultSerializeConfig) {
        DefaultResultDecoratorImpl.defaultSerializeConfig = defaultSerializeConfig;
    }

    public PropertyPreFilter getPropertyPreFilter() {
        return propertyPreFilter;
    }

    public void setPropertyPreFilter(PropertyPreFilter propertyPreFilter) {
        this.propertyPreFilter = propertyPreFilter;
    }

    public SerializeConfig getSerializeConfig() {
        return null == serializeConfig ? getDefaultSerializeConfig() : serializeConfig;
    }

    public void setSerializeConfig(SerializeConfig serializeConfig) {
        this.serializeConfig = serializeConfig;
    }

    @Override
    public Object decorate(Object result, int status) {
        return decorate( result, status, null );
    }

    @Override
    public Object decorate(Object result, int status, String errMsg) {
        SerializeConfig config = getSerializeConfig();
        PropertyPreFilter filter = getPropertyPreFilter();

        String resultJSON = null;
        Decorated decorated = new Decorated( result, status, errMsg );
        if ( null != config && null == filter ) {
            resultJSON = JSON.toJSONString( decorated, config );
        } else if ( null != config && null != filter ) {
            resultJSON = toJSONString( decorated, config, filter );
        } else if ( null == config && null != filter ) {
            resultJSON = JSON.toJSONString( decorated, filter );
        } else if ( null == config && null == filter ) {
            resultJSON = JSON.toJSONString( decorated );
        }
        return resultJSON;
    }

    public static class Decorated {

        final Object response;
        final int status;
        private String errMsg;

        public Decorated(Object response, int status) {
            this.response = response;
            this.status = status;
        }

        public Decorated(Object response, int status, String errMsg) {
            this.response = response;
            this.status = status;
            this.errMsg = errMsg;
        }

        public int getStatus() {
            return status;
        }

        public Object getResponse() {
            return response;
        }

        public String getErrMsg() {
            return errMsg;
        }

        public void setErrMsg(String errMsg) {
            this.errMsg = errMsg;
        }

    }

    //fastjson JSON Object has no method fits such parameters, so create one like this.
    public static String toJSONString(Object object, SerializeConfig config, SerializeFilter filter,
                                            SerializerFeature... features) {
        SerializeWriter out = new SerializeWriter();

        try {
            JSONSerializer serializer = new JSONSerializer( out, config );
            for (com.alibaba.fastjson.serializer.SerializerFeature feature : features) {
                serializer.config(feature, true);
            }

            serializer.config(SerializerFeature.WriteDateUseDateFormat, true);

            if (filter != null) {
                if (filter instanceof PropertyPreFilter) {
                    serializer.getPropertyPreFilters().add(
                            (PropertyPreFilter) filter);
                }

                if (filter instanceof NameFilter) {
                    serializer.getNameFilters().add((NameFilter) filter);
                }

                if (filter instanceof ValueFilter) {
                    serializer.getValueFilters().add((ValueFilter) filter);
                }

                if (filter instanceof PropertyFilter) {
                    serializer.getPropertyFilters()
                            .add((PropertyFilter) filter);
                }
            }

            serializer.write(object);

            return out.toString();
        } finally {
            out.close();
        }
    }

}
